package com.spzx.product.lock;

import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.spzx.common.core.utils.uuid.UUID;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class TestServiceImpl implements TestService{

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 100 请求    0
    @Override
    public synchronized void  testLock1() {
        //从redis获取key是num数据
        String num = (String)stringRedisTemplate.opsForValue().get("num");
        //判断
        if(StringUtils.isBlank(num)) {
            return;
        }

        //num+1 放回到redis
        int value = Integer.parseInt(num);
        stringRedisTemplate.opsForValue().set("num",String.valueOf(++value));
    }

    //setnx分布式锁简单
    // 100 请求    0
    public void  testLock2() {
        String uuid = UUID.randomUUID().toString();
        //1 setnx加锁
        Boolean flag = stringRedisTemplate.opsForValue()
                .setIfAbsent("lock",uuid,3,TimeUnit.SECONDS);
        if(flag) { //加锁成功
            try {

                //  7s

                //从redis获取key是num数据
                String num = (String)stringRedisTemplate.opsForValue().get("num");
                //判断
                if(StringUtils.isBlank(num)) {
                    return;
                }

                //num+1 放回到redis
                int value = Integer.parseInt(num);

                //出异常
                stringRedisTemplate.opsForValue().set("num",String.valueOf(++value));

            } finally {
                //判断
//                if(uuid.equals((String)stringRedisTemplate.opsForValue().get("lock"))) {
//                    //2 释放锁
//                    stringRedisTemplate.delete("lock");
//                }
                //lua脚本保证原子性 释放锁
                //创建对象
                DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
                //lua脚本
                String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                        "then\n" +
                        "    return redis.call(\"del\",KEYS[1])\n" +
                        "else\n" +
                        "    return 0\n" +
                        "end";
                redisScript.setScriptText(script);
                redisScript.setResultType(Long.class);
                //redisTemplate执行lua脚本
                stringRedisTemplate.execute(redisScript,Arrays.asList("lock"), uuid);
            }
        }else{
            try {
                Thread.sleep(100);
                this.testLock2();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
